package org.jeecg.device.util;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public abstract class Device {

    public DeviceInfo getDeviceInfo() throws Exception {
        return new DeviceInfo()
                .setIpList(this.getIpAddress())
                .setMacList(this.getMacAddress())
                .setCpu(this.getCpuSerial())
                .setMainBoard(this.getMainBoardSerial());
    }

    List<String> getIpAddress() throws Exception {
        List<InetAddress> inetAddresses = getLocalAllInetAddress();
        return Optional.ofNullable(inetAddresses).orElse(new ArrayList<>(0))
                .stream()
                .map(e -> e.getHostAddress().toLowerCase())
                .distinct()
                .collect(Collectors.toList());
    }

    List<String> getMacAddress() throws Exception {
        List<InetAddress> inetAddresses = getLocalAllInetAddress();
        return Optional.ofNullable(inetAddresses).orElse(new ArrayList<>(0))
                .stream()
                .map(this::getMacByInetAddress)
                .distinct()
                .collect(Collectors.toList());
    }

    abstract String getCpuSerial() throws Exception;

    abstract String getMainBoardSerial() throws Exception;

    List<InetAddress> getLocalAllInetAddress() throws Exception {
        List<InetAddress> inetAddressList = new ArrayList<>();
        for (Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces();
             networkInterfaces.hasMoreElements();) {
            NetworkInterface networkInterface = (NetworkInterface) networkInterfaces.nextElement();
            for (Enumeration inetAddresses = networkInterface.getInetAddresses();
                 inetAddresses.hasMoreElements();) {
                InetAddress inetAddr = (InetAddress) inetAddresses.nextElement();
                if (!inetAddr.isLoopbackAddress()
                        && !inetAddr.isLinkLocalAddress()
                        && !inetAddr.isMulticastAddress()) {
                    inetAddressList.add(inetAddr);
                }
            }
        }
        return inetAddressList;
    }

    String getMacByInetAddress(InetAddress inetAddr) {
        try {
            byte[] mac = NetworkInterface.getByInetAddress(inetAddr).getHardwareAddress();
            StringBuilder buf = new StringBuilder();
            for (int i = 0; i < mac.length; i++) {
                if (i != 0) {
                    buf.append("-");
                }
                String temp = Integer.toHexString(mac[i] & 0xff);
                if (temp.length() == 1) {
                    buf.append("0").append(temp);
                } else {
                    buf.append(temp);
                }
            }
            return buf.toString().toUpperCase();
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return null;
    }
}
